package com.h5ve.toolkit.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.h5ve.base.api.R;
import com.h5ve.base.constant.AppConstants;
import com.h5ve.base.constant.CommonConstants;
import com.h5ve.base.constant.SqlConstants;
import com.h5ve.base.util.StrUtil;
import com.h5ve.log.annotation.SysLog;
import com.h5ve.system.entity.Menu;
import com.h5ve.system.service.MenuService;
import com.h5ve.toolkit.dto.FieldsDto;
import com.h5ve.toolkit.dto.FormDto;
import com.h5ve.toolkit.entity.*;
import com.h5ve.toolkit.service.ColumnService;
import com.h5ve.toolkit.service.FormService;
import com.h5ve.toolkit.service.GroupInfoService;
import com.h5ve.toolkit.service.TableService;
import com.h5ve.toolkit.util.BuilderUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.util.StrUtil.isEmptyIfStr;

/**
 * @author h5ve
 * @date 2021-03-11 21:57:03
 * @description 表单Controller
 */
@Api("表单管理")
@RestController
@AllArgsConstructor
@RequestMapping(AppConstants.APP_TOOLKIT + "/form")
public class FormController {

    private final JdbcTemplate jdbcTemplate;
    private final FormService formService;
    private final TableService tableService;
    private final ColumnService columnService;
    private final MenuService menuService;
    private final GroupInfoService groupInfoService;

    private QueryWrapper<Form> getQueryWrapper(Form form) {
        return new QueryWrapper<Form>()
                .like(CharSequenceUtil.isNotBlank(form.getName()), "name", form.getName())
                .eq(!StrUtil.isEmptyIfNum(form.getApplicationId()), "application_id", form.getApplicationId())
                .eq(CharSequenceUtil.isNotBlank(form.getType()), "type", form.getType())
                .eq(CharSequenceUtil.isNotBlank(form.getCode()), "code", form.getCode())
                .eq(CharSequenceUtil.isNotBlank(form.getIsMain()), "is_main", form.getIsMain())
                .in(form.getGroupIds() != null && form.getGroupIds().length > 0, "group_id", form.getGroupIds())
                .like(CharSequenceUtil.isNotBlank(form.getTableName()), "table_name", form.getTableName())
                .in(form.getMenuIds() != null, "menu_id", form.getMenuIds())
                //.between(ObjectUtil.isNotNull(form.getStartTime()) && ObjectUtil.isNotNull(form.getEndTime()), "create_time", form.getStartTime(), form.getEndTime())
                .orderByDesc("id");
    }

    /*@ApiOperation("表单列表")
    @SaCheckPermission("form_view")
    @GetMapping("/list")
    public R list(Page page, Form form) {
        IPage<Form> formPage = formService.page(page, getQueryWrapper(form));
        return R.ok(formPage.getRecords(), formPage.getTotal());
    }*/

    /**
     * 动态表单列表分页查询
     *
     * @param page 查询分页参数
     * @param form 查询条件参数
     * @return
     */
    @ApiOperation("表单列表")
    @SaCheckPermission("form_view")
    @GetMapping("/list")
    public R list(Page<Form> page, Form form) {
        if (form.getMenuId() != null) {
            List<Long> list = new LinkedList<>();
            List<Menu> formListByMenuId = findFormListByMenuId(form.getMenuId(), new LinkedList<>());
            if (formListByMenuId.size() > 0) {
                for (Menu m : formListByMenuId) {
                    list.add(m.getId());
                    form.setMenuIds(list);
                }
            }
        }

        if (form.getGroupId() != null) {
            Long[] groupIds = getGroupIds(form.getGroupId());
            form.setGroupIds(groupIds);
        }
        IPage<Form> formPage = formService.page(page, getQueryWrapper(form));
        List<Form> formList = formPage.getRecords();
        formList.stream().forEach(map -> {
            String tableName = map.getTableName().contains(CommonConstants.SQLPREFIX) ? map.getTableName() : CommonConstants.SQLPREFIX + map.getTableName();
            Table table = tableService.getOne(new QueryWrapper<Table>().eq("table_name", tableName));
            if (table != null) {
                map.setIsConfig("1");
                map.setGenWay(table.getGenWay());
                map.setFullTableName(table.getTableName());
            } else {
                map.setIsConfig("0");
            }
        });
        return R.ok(formList, formPage.getTotal());
    }

    private List<Menu> findFormListByMenuId(Long menuId, List<Menu> list) {
        list.add(menuService.getById(menuId));
        List<Menu> list1 = menuService.list(new QueryWrapper<Menu>().eq("parent_id", menuId).eq("type", "M"));
        if (list1.size() > 0) {
            list.addAll(list1);
            for (Menu f : list1) {
                findFormListByMenuId(f.getId(), list);
            }
        }
        return list;
    }

    private Long[] getGroupIds(long groupId) {

        List<GroupInfo> groups = groupInfoService.list();
        Long[] groupIds = new Long[groups.size()];
        if (groups.size() > 0) {
            for (GroupInfo groupInfo : groups) {
                if (groupInfo.getId() == groupId) {
                    groupIds[groups.indexOf(groupInfo)] = groupInfo.getId();
                }
                if (groupInfo.getParentIds() != null && !"".equals(groupInfo.getParentIds())) {
                    String[] groupInfoIds = groupInfo.getParentIds().split(",");
                    for (String id : groupInfoIds) {
                        if (id.equals(groupId + "")) {
                            groupIds[groups.indexOf(groupInfo)] = groupInfo.getId();
                        }
                    }
                }

            }
        }
        return groupIds;
    }

    @ApiOperation("表单查询")
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") Integer id) {
        return R.ok(formService.getById(id));
    }

    @SysLog("表单新增")
    @ApiOperation("表单新增")
    @SaCheckPermission("form_add")
    @PostMapping("/save")
    @Transactional
    public R save(@Validated @RequestBody Form form) {
        if (CharSequenceUtil.isNotBlank(form.getTableName()) && CharSequenceUtil.isNotBlank(form.getType())) {
            List<Form> list = formService.list(new LambdaQueryWrapper<Form>().eq(Form::getName, form.getName()).eq(Form::getIsMain, "1"));
            if (list.size() > 0) {
                return R.error("新增失败：表单名称重复请重新输入！");
            }
        }
        //验证数据表名称
        form = verificationTableName(form);

        //当表单不为空的时候将表名全部转换为小写
        if (CharSequenceUtil.isNotBlank(form.getTableName())) {
            form.setTableName(form.getTableName().toLowerCase());
        }
        //生成查询条件
        QueryWrapper<Table> query = new QueryWrapper<Table>().eq("table_name", "form_" + form.getTableName());
        if ("2".equals(form.getType())) {  //主子表
            String childTable = form.getChildTable();
            if (CharSequenceUtil.isNotBlank(childTable)) {
                JSONArray arr = JSONUtil.parseArray(form.getChildTable());
                List<String> listStr = new ArrayList<>();

                //查找所有子表表名
                for (int i = 0; i < arr.size(); i++) {
                    JSONObject obj = arr.getJSONObject(i);
                    String tableName = obj.getStr("tableName");
                    String childType = obj.getStr("childType");
                    tableName = tableName.contains(CommonConstants.SQLPREFIX) ? tableName : CommonConstants.SQLPREFIX + tableName;
                    //验证表名 子表单表名是否重复
                    if (CharSequenceUtil.isNotEmpty(tableName) && "tempTable".equals(childType)) {
                        listStr.add(tableName);
                    }
                }
                query.or(wrapper -> wrapper.in("table_name", listStr));
            } else {
                return R.error("子表信息为空");
            }
        }
        //验证表名 子表单表名是否重复
        List<Table> formList = tableService.list(query);
        if (formList.size() > 0) {
            return R.error("表名或子表名已存在或不可用，请重新输入！");
        }
        //设置表单版本
        form.setVersion("0");
        //将当前表单信息设置为主版本
        form.setIsMain("1");
        //动态表单信息入库
        formService.save(form);
        //新增数据库表
        createTable(form);
        //新增菜单数据
        createMenu(form);
        return R.ok();
    }

    @SysLog("表单修改")
    @ApiOperation("表单修改")
    @SaCheckPermission("form_edit")
    @PutMapping("/update")
    public R update(@Validated @RequestBody Form form) {
        //设置新版本数据
        List<Form> formList = formService.list(new QueryWrapper<Form>().eq("code", form.getCode()).orderByDesc("length(version)").orderByDesc("version"));
        form.setId(null);
        form.setIsMain("1");
        form.setVersion((Integer.parseInt(formList.get(0).getVersion()) + 1) + "");
        //修改数据库表及table表数据
        createTable(form);
        //判断是新增菜单还是修改菜单
        List<Menu> menus = menuService.list(new LambdaQueryWrapper<Menu>().eq(Menu::getPath, "dynamic/" + form.getCode()));
        if (menus.size() > 0) {
            //修改
            Menu menu = menus.get(0);
            menu.setName(form.getName());
            menu.setParentId(form.getMenuId());
            menuService.update(menu, new LambdaQueryWrapper<Menu>().eq(Menu::getId, menu.getId()));
            //删除冗余菜单
            List<Menu> list = menuService.list(new LambdaQueryWrapper<Menu>().eq(Menu::getPath, "dynamic/" + form.getCode()).ne(Menu::getId, menu.getId()));
            for (Menu menu1 : list) {
                //删除子菜单同事删除菜单
                menuService.remove(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, menu1.getId()).eq(Menu::getType, "F"));
                menuService.removeById(menu1);
            }
        }
        //新增菜单数据
        createMenu(form);

        //查询所有表单所有版本并将所有版本都设置为非主版本
        List<Form> oldForms = formService.list(new QueryWrapper<Form>().eq("code", form.getCode()));
        if (oldForms.size() > 0) {
            for (Form oldForm : oldForms) {
                oldForm.setIsMain("0");
                formService.updateById(oldForm);
            }
        }
        formService.save(form);
        return R.ok();
    }

    @SysLog("表单删除")
    @ApiOperation("表单删除")
    @SaCheckPermission("form_del")
    @DeleteMapping("/remove/{id}")
    public R remove(@PathVariable("id") Integer[] id) {
        return R.ok(formService.removeByIds(Arrays.asList(id)));
    }


    @SaCheckPermission("form_export")
    @GetMapping("/export")
    public void export(Form form, ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        List<Form> list = formService.list(getQueryWrapper(form));
        //ExcelUtil.exportExcel("表单信息", list, Form.class, map, request, response);
    }

    /**
     * 动态表单列表查询
     *
     * @param form 查询条件信息
     * @return 查询结果
     */
    @ApiOperation("动态表单列表")
    @PostMapping("/dynamicList")
    public R dynamicList(@RequestBody FormQuery form) {
        Page<Map<String, Object>> page = new Page<>();
        page.setSize(form.getSize());
        page.setCurrent(form.getCurrent());
        Form form1 = formService.getOne(new QueryWrapper<Form>().eq("code", form.getCode()).eq("is_main", "1"));
        if(form1 == null){
            return R.error("表单信息不存在");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("type", form1.getType());
        if ("1".equals(form1.getType())) {
            // 树表
            List<Map<String, Object>> list = formService.mapFormList(form);
            map.put("data", treeList(list));
            return R.ok(map);
        } else {
            IPage<Map<String, Object>> formPage = formService.mapFormPage(page, form);
            map.put("data", formPage.getRecords());
            map.put("total", formPage.getTotal());
            return R.ok(map);
        }
    }

    /**
     * 动态表单查询
     *
     * @param code 动态表单唯一code编码
     * @param id   动态表单id
     * @return 操作结果
     */
    @ApiOperation("动态表单查询")
    @GetMapping("/dynamicById")
    public R dynamicById(String code, Integer id) {
        Form form = formService.getOne(new QueryWrapper<Form>().eq("code", code).eq("is_main", '1'));
        return R.ok(formService.queryData(form.getTableName(), id, form.getType()), form.getData());
    }

    @ApiOperation("动态表单查询")
    @GetMapping("/dynamicForm")
    public R dynamicFormById(String tableName, Integer id) {
        Form form = formService.getOne(new QueryWrapper<Form>().eq("table_name", tableName));
        return R.ok(formService.queryData(tableName, id), form.getData());
    }

    @PostMapping("dynamicSave")
    public R dynamicSave(@RequestBody FormDto formDto) throws Exception{

        Form formData = formService.getOne(new QueryWrapper<Form>().eq("code", formDto.getCode()).eq("is_main", "1").last("limit 1"));
        if(formData == null){
            return R.error("表单信息不存在");
        }
        String msg = formService.saveData(formData, formDto);
        if (!"true".equals(msg)) {
            return R.error(msg);
        }
        return R.ok("新增成功!");
    }

    /**
     * 动态表单数据修改
     *
     * @param form 表单数据
     * @return 操作结果
     */
    @ApiOperation("动态表单数据修改")
    @PostMapping("/dynamicUpdate")
    public R dynamicUpdate(@RequestBody Form form) {

        return formService.updateData(form);
    }

    @ApiOperation("动态表单删除")
    @DeleteMapping("/dynamicRemove")
    public R dynamicRemove(String tableName, Integer[] ids) {
        formService.removeData(tableName, ids);
        return R.ok();
    }

    @GetMapping("/column/{tableName}")
    public R column(@PathVariable String tableName) {
        Table table = tableService.getOne(new QueryWrapper<Table>().eq("table_name", CommonConstants.PREFIX + tableName));
        List<Column> columnList = columnService.list(new QueryWrapper<Column>().eq("table_id", table.getId()));
        return R.ok(columnList);
    }

    /**
     * 获取表单唯一code编码
     *
     * @return
     */
    @SysLog("获取表单唯一code")
    @ApiOperation("获取表单唯一code")
    @SaCheckPermission("form_add")
    @GetMapping("/getFormCode")
    @Transactional(rollbackFor = Exception.class)
    public R getFormCode() {
        return R.ok(IdWorker.get32UUID());
    }

    /**
     * 新增表单数据验证
     * ————验证表单名称是否重复
     * ————验证数据库表名是否重复
     *
     * @param str
     * @return
     */
    @PostMapping("/duplicateChecking")
    public R duplicateChecking(@RequestBody String str) {
        if (StrUtil.isNotBlank(str)) {
            List<Form> formName = formService.list(new LambdaQueryWrapper<Form>().eq(Form::getName, str).eq(Form::getIsMain, "1"));
            if (0 < formName.size()) {
                Form form = formName.get(0);
                if (str.equals(form.getName())) {
                    return R.error("表单名称已存在请重新输入！");
                }
            }
        }
        return R.ok();
    }

    /**
     * 文件导入
     *
     * @param file Excel文件输入流
     */
    @ApiOperation("表单文件导入")
    @PostMapping("/fieldsTemplateAnalysis")
    public R fieldsTemplateAnalysis(MultipartFile file, HttpServletRequest request) throws Exception {
        if (file.isEmpty()) {
            return R.error("上传文件不能为空");
        }
        // 获取文件的后缀名
        /*String fileFormat = UploadUtil.getFileSuffix(file.getOriginalFilename());
        // 获取文件的后缀名
        String type = UploadUtil.getType(fileFormat);
        if ("other".equals(type)) {
            return R.error("不支持的文件格式");
        }*/

        byte[] byteArr = file.getBytes();
        InputStream inputStream = new ByteArrayInputStream(byteArr);

        /*Object data1 = ExcelUtils.enteringExcelMap(inputStream).get("data");
        List<Map<String, Object>> data = (List<Map<String, Object>>) data1;*/
        List<FieldsDto> fieldsTemplateVOS = new ArrayList<>();
        /*for (Map<String, Object> map : data) {
            FieldsTemplateVO fieldsTemplateVO = new FieldsTemplateVO();
            switch (map.get("类型").toString()) {
                case "单行文本":
                    fieldsTemplateVO.setType("input");
                    break;
                case "多行文本":
                    fieldsTemplateVO.setType("textarea");
                    break;
                case "计数器":
                    fieldsTemplateVO.setType("inputNumber");
                    break;
                case "下拉选择":
                    fieldsTemplateVO.setType("select");
                    break;
                case "单选框":
                    fieldsTemplateVO.setType("radio");
                    break;
                case "多选框":
                    fieldsTemplateVO.setType("checkbox");
                    break;
                case "时间选择器":
                    fieldsTemplateVO.setType("time");
                    break;
                case "日期选择器":
                    fieldsTemplateVO.setType("date");
                    break;
                case "评价":
                    fieldsTemplateVO.setType("rate");
                    break;
                case "颜色选择器":
                    fieldsTemplateVO.setType("inputColor");
                    break;
                case "开关":
                    fieldsTemplateVO.setType("switch");
                    break;
                case "滑块":
                    fieldsTemplateVO.setType("slider");
                    break;
                case "文字":
                    fieldsTemplateVO.setType("font");
                    break;
                case "文件":
                    fieldsTemplateVO.setType("upload");
                    break;
                case "级联选择器":
                    fieldsTemplateVO.setType("cascader");
                    break;
                case "子表单":
                    fieldsTemplateVO.setType("childForm");
                    break;
                default:
                    throw new Exception("表格中存在未知属性:【" + map.get("类型").toString() + "】");
            }

            fieldsTemplateVO.setFieldName(map.get("字段名").toString());
            fieldsTemplateVOS.add(fieldsTemplateVO);
        }*/
        return R.ok(fieldsTemplateVOS);
    }

    /**
     * 获取菜单树
     *
     * @return
     */
    @SysLog("获取菜单树")
    @ApiOperation("获取菜单树")
    @SaCheckPermission("form_add")
    @GetMapping("/getMenuTree")
    @Transactional(rollbackFor = Exception.class)
    public R getMenuTree() {
        List<Map<String, Object>> list = jdbcTemplate.queryForList(SqlConstants.MENU_TREE);
        return R.ok(list);
    }

    /**
     * 动态表单查询（所有动态表单）
     *
     * @return
     */
    @ApiOperation("表单列表-所有列表")
    @SaCheckPermission("form_view")
    @GetMapping("/lists")
    public R lists() {
        List<Table> list = tableService.list();
        return R.ok(list, list.size());
    }

    /**
     * 验证数据库表名称是否重复
     * —— 如果重复则在后面添加数值来避免重复
     *
     * @param form
     * @return
     */
    private Form verificationTableName(Form form) {
        if (CharSequenceUtil.isNotBlank(form.getTableName()) && CharSequenceUtil.isNotBlank(form.getType())) {
            List<Form> list = formService.list(new LambdaQueryWrapper<Form>().eq(Form::getTableName, form.getTableName()));
            if (list.size() > 0) {
                Long index = 0L;
                Boolean condition = true;
                String substring = form.getTableName().substring(form.getTableName().length() - 1, form.getTableName().length());
                try {
                    index = Long.valueOf(substring);
                    index += 1L;
                } catch (NumberFormatException e) {
                    index = 0L;
                    condition = false;
                }
                if (condition) {
                    form.setTableName(form.getTableName().substring(0, form.getTableName().length() - 1) + index);
                } else {
                    form.setTableName(form.getTableName() + index);
                }
                form = verificationTableName(form);
            }
            return form;
        }
        return form;
    }

    /**
     * 表单创建 / 修改
     *
     * @param form
     */
    public void createTable(Form form) {
        Table table = tableService.getOne(new QueryWrapper<Table>().eq("code", form.getCode()));
        //新建表单
        if (table == null) {
            //创建表
            table = BuilderUtil.createForm(form);

            //设置树表信息
            if (CharSequenceUtil.isNotEmpty(form.getTreeName())) {
                String options = String.format("{\"treeId\":\"id\",\"treeName\":\"%s\",\"treeParentId\":\"parent_id\"}", form.getTreeName());
                table.setOptions(options);
            }
//            String options = JSONUtil.toJsonStr(form.getParams());
            table.setTableName(CommonConstants.SQLPREFIX + form.getTableName());
            tableService.save(table);
            if (table.getColumns() != null && table.getColumns().size() > 0) {
                for (Column column : table.getColumns()) {
                    column.setTableId(table.getId());
                    columnService.save(column);
                }
            }

            //创建SQL脚本
            jdbcTemplate.execute(BuilderUtil.createTable(table));   //创建表

            //创建子表数据
            if (CharSequenceUtil.isNotBlank(form.getChildTable()) && !"{}".equals(form.getChildTable())) {
                JSONArray jsonArray = JSONUtil.parseArray(form.getChildTable());
                if (jsonArray != null && jsonArray.size() > 0) {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        String tableName = jsonObject.getStr("tableName");
                        String tableComment = jsonObject.getStr("tableComment");
                        if (isEmptyIfStr(tableName)) {
                            continue;
                        }
                        Table t = tableService.getOne(new QueryWrapper<Table>().eq("table_name", tableName.contains(CommonConstants.SQLPREFIX) ? tableName : CommonConstants.SQLPREFIX + tableName).eq("del_flag", "0"));
                        //若是子表单的数据，t为null ，这里只创建子表单的表数据
                        if (t == null) {
                            //创建子表
                            t = BuilderUtil.createForm(form, tableName);
                            t.setChildTable(null);
                            t.setTableComment(tableComment);

                            //设置子表的描述信息

                            tableService.save(t);  //保存dev_table数据

                            if (t.getColumns() != null && t.getColumns().size() > 0) {
                                for (Column column : t.getColumns()) {
                                    column.setTableId(t.getId());
                                    column.setDictType(column.getDictType());
                                    columnService.save(column);  //保存dev_column数据
                                }

                                //创建SQL脚本
                                jdbcTemplate.execute(BuilderUtil.createTable(t));   //创建表
                            }
                        }
                    }
                }
            }
        } else {
            //todo 更新表结构
            Table table1 = BuilderUtil.createForm(form);

            table1.setId(table.getId());

            tableService.updateById(table1);
            // 更新列
            List<Column> columnList = columnService.list(new QueryWrapper<Column>().eq("table_id", table1.getId()));
            final Map<String, Long> columnMap = columnList.stream().collect(Collectors.toMap(Column::getColumnName, Column::getId));
            if (table1.getColumns() != null && table1.getColumns().size() > 0) {
                if (columnList.size() > 0) {
                    final Map<String, String> colMap = table1.getColumns().stream().collect(Collectors.toMap(Column::getColumnName, Column::getColumnName));
                    for (Column column : columnList) {
                        final String name = colMap.get(column.getColumnName());
                        if (name == null) {
                            // 删除列数据
                            columnService.removeById(column.getId());
                        }
                    }
                }
                for (Column column : table1.getColumns()) {
                    final Long id = columnMap.get(column.getColumnName());
                    column.setTableId(table1.getId());
                    if (id != null) {
                        column.setId(id);
                        // 更新列数据
                        columnService.updateById(column);
                    } else {
                        // 保存列数据
                        columnService.save(column);
                    }
                }
            }
            //更新数据库中的表结构
//            String updatesql = BuilderUtil.updateTableMethod(table1);
//            if (updatesql != null && !Objects.equals(updatesql, "")) {
//                // 判断表是否存在，存在就直接删除掉
//                jdbcTemplate.execute("DROP TABLE IF EXISTS " + table1.getTableName());
//                jdbcTemplate.execute(updatesql);
//            }
            // 判断表是否存在
            String querySql = "SELECT count( * ) as count  FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = ( SELECT DATABASE ( ) ) AND table_name = '" + table1.getTableName() + "' AND table_type = 'BASE TABLE'";
            List<Map<String, Object>> maps = jdbcTemplate.queryForList(querySql);
            if (Integer.valueOf(maps.get(0).get("count").toString()) > 0) {
                // 修改表
                String updatesql = BuilderUtil.updateTable(table1, columnList);
                if (updatesql != null && !Objects.equals(updatesql, "")) {
                    jdbcTemplate.execute(updatesql);
                }
            } else {
                // 创建表
                String updatesql = BuilderUtil.updateTableMethod(table1);
                if (updatesql != null && !Objects.equals(updatesql, "")) {
                    jdbcTemplate.execute(updatesql);
                }
            }

            //更新子表数据
            if (CharSequenceUtil.isNotBlank(form.getChildTable()) && !"{}".equals(form.getChildTable())) {
                //记录原始的子表数据，方便比对那些已经被删除的子表数据
                String oldChildTable = table.getChildTable();
                //原始子表数据中 类型为tempTable（子表单）的表名集合
                List<String> oldTableNameList = new ArrayList<>();
                JSONArray oldArray = JSONUtil.parseArray(oldChildTable);
                for (int i = 0; i < oldArray.size(); i++) {
                    JSONObject oldObj = oldArray.getJSONObject(i);
                    String tableName = oldObj.getStr("tableName");
                    String childType = oldObj.getStr("childType");
                    if ("tempTable".equals(childType) && CharSequenceUtil.isNotEmpty(tableName)) {  //临时子表单
                        oldTableNameList.add(tableName);
                    }
                }

                JSONArray jsonArray = JSONUtil.parseArray(form.getChildTable());
                if (jsonArray != null && jsonArray.size() > 0) {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                        String tableName = jsonObject.getStr("tableName");
                        String tableComment = jsonObject.getStr("tableComment");

                        //tempTable子表单     relationTable关联表
                        String childType = jsonObject.getStr("childType");

                        if (isEmptyIfStr(tableName)) {
                            continue;
                        }


                        //需要判断是子表单 还是关联表
                        //若是子表单的数据，t为null ，这里只创建子表单的表数据
                        if ("tempTable".equals(childType)) {  //子表单

                            //新子表表名若存在旧子表数据中 则移除掉，剩下的表名就是界面被删除掉的子表单，这些表需要删除掉
                            oldTableNameList.remove(tableName);

                            Table t = tableService.getOne(new QueryWrapper<Table>().eq("table_name", CommonConstants.SQLPREFIX + tableName));
                            if (t == null) {
                                //创建子表
                                t = BuilderUtil.createForm(form, tableName);
                                t.setChildTable(null);
                                t.setTableComment(tableComment);
                                tableService.save(t);  //保存dev_table数据

                                if (t.getColumns() != null && t.getColumns().size() > 0) {
                                    for (Column column : t.getColumns()) {
                                        column.setTableId(t.getId());
                                        columnService.save(column);  //保存dev_column数据
                                    }
                                    //SQL脚本创建表
                                    jdbcTemplate.execute(BuilderUtil.createTable(t));   //创建表
                                }
                            } else {
                                Table t1;
                                t1 = BuilderUtil.createForm(form, tableName);
                                t1.setId(t.getId());
                                t1.setChildTable(null);
                                t1.setTableComment(tableComment);
                                tableService.updateById(t1);

                                //更新列
                                List<Column> colList = columnService.list(new QueryWrapper<Column>().eq("table_id", t1.getId()));
                                if (colList != null && colList.size() > 0) {
                                    columnService.removeBatchByIds(colList);  //删除之前的所有列数据
                                }
                                if (t1.getColumns() != null && t1.getColumns().size() > 0) {
                                    for (Column column : t1.getColumns()) {
                                        column.setTableId(t1.getId());
                                        columnService.save(column);
                                    }

                                    //SQL脚本更新表
                                    jdbcTemplate.execute(BuilderUtil.updateTable(t1));
                                }
                            }
                        }
                    }
                }

                //移除那些 在界面中已经删除的子表单
                if (CollUtil.isNotEmpty(oldTableNameList)) {
                    for (String s : oldTableNameList) {
                        Table t = tableService.getOne(new QueryWrapper<Table>().eq("table_name", CommonConstants.SQLPREFIX + s));
                        if (ObjectUtil.isNotEmpty(t)) {
                            //删除子表列数据 dev_column
                            columnService.remove(new QueryWrapper<Column>().eq("table_id", t.getId()));

                            //删除子表结构
                            jdbcTemplate.execute("drop table if exists `" + CommonConstants.SQLPREFIX + s + "` ");

                            //删除dev_table
                            tableService.removeById(t.getId());
                        }
                    }
                }
            }
        }
    }

    private void createMenu(Form form) {
        //新增菜单数据
        Menu menu = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", form.getMenuId()).eq("path", "dynamicForm/" + form.getCode()));
        if (menu == null) {
            menu = new Menu();
            menu.setParentId(form.getMenuId());
            menu.setName(form.getName());
            //menu.setApplicationId(1);
            menu.setType("C");
            menu.setPath("dynamic/" + form.getCode());
            menu.setComponent("toolkit/dynamic/index");
            menu.setIcon("star");
            menu.setNoCache("0");
            menu.setSort(1);
            menu.setStatus("0");
            menuService.save(menu);
        } else {
            menu.setName(form.getName());
            menuService.updateById(menu);
        }
        //新增菜单中资源数据
        JSONArray jsonArray = JSONUtil.parseArray(form.getBtnData());
        if (jsonArray != null && jsonArray.size() > 0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                Menu menu1 = new Menu();
                switch (jsonObject.getStr("name")) {
                    case "新增":
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_add"));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_add");
                        }
                        break;
                    case "搜索":
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_view"));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_view");
                        }
                        break;
                    case "修改":
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_edit"));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_edit");
                        }
                        break;
                    case "删除":
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_del"));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_del");
                        }
                        break;
                    case "导出":
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_export"));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_export");
                        }
                        break;
                    default:
                        menu1 = menuService.getOne(new QueryWrapper<Menu>().eq("parent_id", menu.getId()).eq("perms", form.getCode() + "_" + jsonObject.getStr("permissions")));
                        if (menu1 == null) {
                            menu1 = new Menu();
                            menu1.setPerms(form.getTableName() + "_" + jsonObject.getStr("permissions"));
                        }
                        break;
                }
                menu1.setParentId(menu.getId());
                menu1.setName(form.getName() + jsonObject.getStr("name"));
                //menu1.setApplicationId(1);
                menu1.setType("F");
                menu1.setComponent("#");
                menu1.setNoCache("0");
                menu1.setSort(i);
                menu1.setStatus("0");
                if (menu1.getId() == null) {
                    menuService.save(menu1);
                } else {
                    menuService.updateById(menu1);
                }
            }
        }
    }

    /**
     * 动态表单查询：根据表唯一id
     *
     * @param code 动态表单唯一code编码
     * @return
     */
    @ApiOperation("表单查询-通过编码")
    @GetMapping("/getByCode")
    public R getByCode(@RequestParam String code) {
        if (code == null || "".equals(code)) {
            return R.error("编码不能为空");
        }
        Form form = formService.getOne(new QueryWrapper<Form>().eq("code", code).eq("is_main", "1"));
        if ("1".equals(form.getType())) {  // 树表
            Table table = tableService.getOne(new QueryWrapper<Table>().eq("table_name", "form_" + form.getTableName()));
            if (table != null) {
                if (CharSequenceUtil.isNotBlank(table.getOptions()) && !"{}".equals(table.getOptions())) {
                    JSONObject jsonObject = JSONUtil.parseObj(table.getOptions());
                    form.setTreeId(jsonObject.getStr("treeId"));
                    form.setTreeName(jsonObject.getStr("treeName"));
                    form.setTreeParentId(jsonObject.getStr("treeParentId"));
                }
            }
        } else if ("2".equals(form.getType())) {  //主子表
            Table table = tableService.getOne(new QueryWrapper<Table>().eq("table_name", "form_" + form.getTableName()));
            if (table != null) {
                form.setChildTable(table.getChildTable());
            }
        }
        return R.ok(form);
    }

    private List<Map<String, Object>> treeList(List<Map<String, Object>> list) {
        List<Map<String, Object>> par = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        for (Map<String, Object> m : list) {
            if (m.get("parent_id") == null) {
                par.add(m);
            }
            map.put(m.get("id") + "", m);
        }
        for (Map<String, Object> m : list) {
            if (m.get("parent_id") != null) {
                Map<String, Object> father = (Map<String, Object>) map.get(m.get("parent_id") + "");
                if (CollUtil.isNotEmpty(father)) {  //找到父节点 设置父子关系
                    if (father.containsKey("childs")) {
                        List<Map<String, Object>> childs = (List<Map<String, Object>>) father.get("childs");
                        childs.add(m);
                        father.put("childs", childs);
                    } else {
                        List<Map<String, Object>> childs = new ArrayList<>();
                        childs.add(m);
                        father.put("childs", childs);
                    }
                } else {  //没有找到父节点  本身作为父节点
                    par.add(m);
                }
            }
        }
        return par;
    }
}
